package com.pro.mianshiti;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author Sanmier
 * @version 1.0
 * @date 2024/4/23
 * 编写一个 java 函数，实现获取 1000 个用户昵称的能力，具体要求如下：
 * 提供一个函数 Service.get(List<Long> userIds)，支持传入 1000 个用户 ID，返回用户 ID 及其对应的昵称
 * 在 Service.get 内部，通过调用 UserService.getUserMap(List<Long> userIds)获取数据，但 UserService.getUserMap 每次最多只接收 50 个用户 ID，且该接口一次请求耗时100ms
 * Service.get(List<Long> userIds)函数需要将所有 1000 个传入的用户 ID 一次返回，并且耗时需要保证在 200ms 以内
 */
public class Service {
    public Map<Long, String> get(List<Long> userIds) {
        Map<Long, String> resultMap = new ConcurrentHashMap<>(); // 使用线程安全的 ConcurrentHashMap

        // 每次最多处理50个用户ID
        int batchSize = 50;

        // 计算需要分成几批请求
        int batches = (int) Math.ceil((double) userIds.size() / batchSize);

        // 创建 ThreadPoolExecutor
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                20, // 核心线程数，这里使用 CPU 核心数
                20, // 最大线程数，这里使用 CPU 核心数
                0L, TimeUnit.MILLISECONDS, // 线程空闲时间
                new SynchronousQueue<>() // 任务队列
        );

        // 存储每个批次的 Future
        List<Future<Map<Long, String>>> futures = new ArrayList<>();

        for (int i = 0; i < batches; i++) {
            // 计算当前批次要处理的用户ID范围
            int start = i * batchSize;
            int end = Math.min(start + batchSize, userIds.size());
            List<Long> batchIds = userIds.subList(start, end);

            // 创建一个 Callable 任务
            Callable<Map<Long, String>> callableTask = new UserMapTask(batchIds);

            // 提交任务给 ThreadPoolExecutor，返回一个 Future
            Future<Map<Long, String>> future = executor.submit(callableTask);

            futures.add(future);
        }

        // 等待所有 Future 完成并将结果合并到 resultMap 中
        for (Future<Map<Long, String>> future : futures) {
            try {
                resultMap.putAll(future.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }

        // 关闭 ThreadPoolExecutor
        executor.shutdown();
        return resultMap;
    }

    // Callable 任务，用于获取用户昵称
    static class UserMapTask implements Callable<Map<Long, String>> {
        private List<Long> userIds;

        public UserMapTask(List<Long> userIds) {
            this.userIds = userIds;
        }

        @Override
        public Map<Long, String> call() throws Exception {
            return new UserService().getUserMap(userIds);
        }
    }

    public static void main(String[] args) {
        Service service = new Service();
        List<Long> userIds = new ArrayList<>();
        for (long i = 1; i <= 1000; i++) {
            userIds.add(i);
        }

        long startTime = System.currentTimeMillis();
        Map<Long, String> result = service.get(userIds);
        long endTime = System.currentTimeMillis();
        System.out.println("耗时：" + (endTime - startTime) + "ms");
        System.out.println("结果数量：" + result.size());
        System.out.println("结果：" + result);
    }
}

class UserService{
    public Map<Long, String> getUserMap(List<Long> userIds){
        if(userIds == null || userIds.size() > 50){
            throw new RuntimeException("userids more than 50");
        }
        Map<Long, String> result = new HashMap();
        for(Long userId : userIds){
            result.put(userId, "test");
        }
        return result;
    }
}